#include "dma1_usart0_rx_driver.h"
#include <stdio.h>

uint8_t dma_receive_data[1024];
uint32_t receive_len = 0;

void send_byte_dma(uint8_t data)
{
    // 在这里通知DMA，待发送数据的地址，和让它干活
    // 设置DMA所用内存地址，就是数据来源地址
    dma_memory_address_config(DMA1, DMA_CH7, DMA_MEMORY_0, (uint32_t)&data);
    // 设置DMA所发送的数据长度
    dma_transfer_number_config(DMA1, DMA_CH7, 1); // 注意看传入参数是一个8bit data，则长度为1

    // 开启DMA传输，dma_channel_enable函数开启DMA通道的传输，注意通道每一次发送完成会自动关闭，每一次发新数据都要调用这个函数
    dma_channel_enable(DMA1, DMA_CH7);

    // 等待本次传输完成
    while (RESET == dma_flag_get(DMA1, DMA_CH7, DMA_FLAG_FTF))
        ;
    dma_flag_clear(DMA1, DMA_CH7, DMA_FLAG_FTF); // 完成后清理标记
}

// int fputc(int ch, FILE *f)
// {
//     // send_byte((uint8_t)ch);
//     send_byte_dma((uint8_t)ch);
//     return ch;
// }

/**
 * 外设到内存
 * usart0_rx对应通道2或5,选择5
 */
void dma1_usart0_rx_config(void)
{
    // 时钟
    rcu_periph_clock_enable(RCU_DMA1);
    //
    dma_deinit(DMA1, DMA_CH5);

    // 创建结构体
    dma_single_data_parameter_struct dsdps;
    // 初始化结构体
    dma_single_data_para_struct_init(&dsdps);

    // 5 方向:外设到内存
    dsdps.direction = DMA_PERIPH_TO_MEMORY;
    // 6 外设地址
    dsdps.periph_addr = (uint32_t)(&USART_DATA(USART0));
    // 7 开启外设地址增长,不增长
    dsdps.periph_inc = DMA_PERIPH_INCREASE_DISABLE;

    // 8 设置内存地址
    dsdps.memory0_addr = (uint32_t)dma_receive_data;
    // 9 内存地址增长
    dsdps.memory_inc = DMA_MEMORY_INCREASE_ENABLE;

    // 10 设置数据长度
    dsdps.number = 1024;

    // 11 数据宽度
    dsdps.periph_memory_width = DMA_PERIPH_WIDTH_8BIT;

    // 12 设置优先级
    dsdps.priority = DMA_PRIORITY_ULTRA_HIGH;

    // 13 初始化dma
    dma_single_data_mode_init(DMA1, DMA_CH5, &dsdps);

    // 14 选择通道的具体功能
    dma_channel_subperipheral_select(DMA1, DMA_CH5, DMA_SUBPERI4);

    //
    dma_channel_enable(DMA1, DMA_CH5);
}

void on_usart0_recv(void)
{
    printf("recv:%s,len=%d\n", dma_receive_data, receive_len);
}

// void USART0_IRQHandler(void)
//{
//     // 不用理会RBNE,因为有数据,DMA自动搬走
//     if (SET == usart_interrupt_flag_get(USART0, USART_INT_FLAG_IDLE))
//     {
//         // 读取缓冲区,清除idle标志
//         usart_data_receive(USART0);

//        // 计算接收长度
//        receive_len = 1024 - dma_transfer_number_get(DMA1, DMA_CH5);
//        dma_receive_data[receive_len] = '\0';
//        on_usart0_recv();

//        dma_channel_disable(DMA1, DMA_CH5);
//        dma_flag_clear(DMA1, DMA_CH5, DMA_FLAG_FTF);
//        dma_channel_enable(DMA1, DMA_CH5);
//    }
//}

void dma1_usart0_rx_test(void)
{
    dma1_usart0_rx_config();

    while (1)
    {
    }
}